import java.util.*;

public class Unit extends BitSet{
	private Object symbol;
	private int size;

	// Constructor
	public Unit(int nbits, Object symbol){
		super(nbits);
		this.size = nbits;
		this.reset();
		this.symbol = symbol;
	}

	// Methods
	public Object getSymbol(){
		return symbol;
	}

	public void setSymbol(Object sym){
		this.symbol = sym;
	}

	public void shiftLeft(){
		for(int i=0;i<this.size-1;i++){
			this.set(i,this.get(i+1));
		}
		this.clear(size-1);
	}

	public void shiftRight(){
		for(int i=this.size-1;i>0;i--){
			this.set(i,this.get(i-1));
		}
		this.clear(0);
	}
	
	public void reset(){
		this.set(0, this.size, true);
	}

	public void setBits(String bits){
		int length = bits.length();
		if(length == this.size){
			for(int i=0;i<length;i++){
				this.set(i,(bits.charAt(i)=='1'));
			}
		}
	}
	
	public int nextSetBit(){
		return super.nextSetBit(0);
	}
	
		
	public int lastSetBit(){
		int result = -1;
		for(int i=this.size-1;i>=0;i--){
			if(this.get(i)){
				result = i;
				break;
			}
		}
		return result;
	}
	
	public void randomState(){
		for(int i=0;i<size;i++){
			this.set(i,((int)(Math.random()*2) == 1)?true:false);
		}
	}
		
	public Object cloneShiftLeft(){
		Unit clone = (Unit) this.clone();
		clone.shiftLeft();
		return clone;
	}
	
	public Object cloneShiftRight(){
		Unit clone = (Unit) this.clone();
		clone.shiftRight();
		return clone;
	}

	public boolean isFound(){
		return (this.cardinality() == 1);
	}

	// Override Methods
	public boolean equals(Object obj){
		if(obj instanceof Unit){
			Unit unit = (Unit) obj;
			return (super.equals(obj) && this.symbol.equals(unit.getSymbol()));
		}else{
			return false;
		}
	}

	public Object clone(){
		Unit clone = (Unit) super.clone();
		clone.setSymbol(this.getSymbol());
		return clone;
	}

	public String toString(){
		//return this.symbol+((this.isFound())?"*":" ")+super.toString();
		String bits = "";
		for(int i=0;i<size;i++){
			bits = bits+((this.get(i))?"1":"0");
		}
			
		return this.symbol+((this.isFound())?"*":" ")+bits;
	}
	
	public int size(){
		return size;
	}
	
	public boolean rAnd(BitSet bit){
		Unit tmp = (Unit) this.clone();
		super.and(bit);
		return !(this.equals(tmp));
	}
	
	public boolean rAndNot(BitSet bit){
		Unit tmp = (Unit) this.clone();
		super.andNot(bit);
		return !(this.equals(tmp));
	}
	
	public boolean rOr(BitSet bit){
		Unit tmp = (Unit) this.clone();
		super.or(bit);
		return !(this.equals(tmp));
	}

}